import {
    _decorator,
    Component,
    EventTouch,
    Node,
    SpriteFrame,
    UITransform,
    Vec2,
    Vec3,
} from 'cc';
const { ccclass, property } = _decorator;

interface IDragAgentData {
    /**
     * 拖拽时显示的 SpriteFrame 或 Node
     *
     * @type {(SpriteFrame | Node)}
     * @memberof IDragAgentData
     */
    icon?: SpriteFrame | Node;
    /**
     * 拖拽时候所携带的数据，在放置的时候会传给 onDropDragAgent 方法
     *
     * @type {*}
     * @memberof IDragAgentData
     */
    sourceData?: any;

    /**
     * 可以对显示的节点进行处理
     *
     * @memberof IDragAgentData
     */
    onShow?: (node: Node) => void;
}

interface IDragDropListener<SourceData = any> {
    /**
     * 触摸到监听面板，可以在这里做一些游戏逻辑的处理
     *
     * @param {EventTouch} event
     * @memberof IDragDropListener
     */
    onTouchTestPanelStart?(event: EventTouch);

    /**
     * 在监听面板上移动，可以在这里做一些游戏逻辑的处理
     *
     * @param {EventTouch} event
     * @memberof IDragDropListener
     */
    onTouchTestPanelMove?(event: EventTouch);

    /**
     * 触摸监听面板结束，可以在这里做一些游戏逻辑的处理
     *
     * @param {EventTouch} event
     * @memberof IDragDropListener
     */
    onTouchTestPanelEnd?(event: EventTouch);
    /**
     * 取消触摸监听面板，可以在这里做一些游戏逻辑的处理
     *
     * @param {EventTouch} event
     * @memberof IDragDropListener
     */
    onTouchTestPanelCancel?(event: EventTouch);

    /**
     * 如果不实现此方法则使用默认的方法查找被按压的节点
     *
     * @param {EventTouch} event
     * @param {Array<Node>} dragNodes
     * @return {*}  {Node}
     * @memberof IDragDropListener
     */
    onFindTarget?(event: EventTouch, dragNodes: Array<Node>): Node;

    /**
     * 查找容器
     *
     * @param {Node} dragAgent 被拖拽的节点
     * @param {Array<Node>} containers 容器数组
     * @param {(node1: Node, node2: Node) => boolean} intersects 一个判断是否相交的默认方法
     * @return {*}  {Node}
     * @memberof IDragDropListener
     */
    onFindContainer?(
        dragAgent: Node,
        containers: Array<Node>,
        intersects: (node1: Node, node2: Node) => boolean,
    ): Node;

    /**
     * 获取显示拖拽代理所需要的数据
     *
     * @param {Node} touchTarget
     * @param {Vec2} uiLocation
     * @return {*}  {IDragAgentData}
     * @memberof IDragDropListener
     */
    onCreateDragAgentData(
        touchTarget: Node,
        uiLocation: Vec2,
    ): IDragAgentData;

    /**
     * 拖放监听
     *
     * @param {Node} container
     * @param {Node} dragAgent
     * @param {SourceData} sourceData
     * @memberof IDragDropListener
     */
    onDropAgent(container: Node, dragAgent: Node, sourceData: SourceData);
}

@ccclass('DragManager')
export class DragManager<SourceData = any> extends Component {
    private dragDropListener: IDragDropListener<SourceData>;
    private sourceData: SourceData = null;
    public dragAgent: Node = null;

    //容器数组，为了做位置的判断
    private containers: Array<Node> = [];
    // 需要拖拽的节点
    private dragNodes: Array<Node> = [];

    private touchTestPanel: Node = null;
    private touchTransform: UITransform = null;
    private touchStartPosition: Vec3 = null;
    private isTouching = false;
    private delayShowDragAgent: Runnable = null;

    private autoRemove = true;

    private _delayMap = new Map<string, number>();
    private _clickEventMap = new Map<string, TouchEvent>();
    private _delayShowTimer = null;
    private _currentTarget: Node = null;

    public get dragging(): boolean {
        return this.dragAgent?.parent != null;
    }

    start() {}

    update(deltaTime: number) {}
}
